//
//  Properties.swift
//  BJ12366Swift
//
//  Created by ZRAR on 16/2/25.
//  Copyright © 2016年 ZRAR. All rights reserved.
//

import UIKit

class Properties: NSObject {
    
    //储存属性
    struct fixedLengthRange {
        
        var firstValue:Int
        let length:Int
    }
    //实例包含了一个变量存储属性和一个常量存储属性，常量存储属性在初始化的时候赋值，之后不能改变
    var rangeOfTreeItems = fixedLengthRange(firstValue: 0, length: 3)
    //常量结构体的存储属性
    let rangeOfFourItems = fixedLengthRange(firstValue: 0, length: 4)
    override init() {
      super.init()
    
        rangeOfTreeItems.firstValue = 7
       // rangeOfFourItems.firstValue = 4,因为结构体在申明的时候是常量，所以这里会报错
    }
    //由于结构体是属于值类型，当值类型的实例被申明为常量的时候，它的所有属性就变成了常量
    //属于引用类型的类（class）则不一样，把一个引用类型的实例赋值给一个常量后，仍然可以修改实例的变量属性
    
    class DataImporter {
        //这个类是一个将外部文件中的数据导入的类，初始化会消耗不少时间
        var fileName = "data.txt"
    }
    class DataMananger {
        
        lazy var importer = DataImporter()
        var data = [String]()
        
    }
    func lazySaveProperties(){
        
        //延迟存储属性是指当第一个被调用的时候才会计算初始值的属性。在属性声明钱使用lazy来标示一个延迟存储属性。
        //必须申明成变量var关键字
        let manager = DataMananger()
        manager.data.append("some data")
        //DataImporter没有创建
        print(manager.importer.fileName)
        //现在被创建
    }
    //计算属性 计算属性不直接存储值，而是提供一个getter和一个可选的setter,来间接获取和设置其他属性或变量的值
    struct Point {
        
        var x = 0.0,y = 0.0
    }
    struct Size {
        var width = 0.0, height = 0.0
    }
    struct Rect {
        
        var origin = Point()
        var size = Size()
        var center:Point{
            get{
                //根据原点确定中心
                let centerx = origin.x + (size.width/2)
                let centery = origin.y + (size.height/2)
                return Point(x: centerx, y: centery)
            }
            set(newCenter){
                //根据中心确定原点,newCenter可以省略˜
                origin.x = newCenter.x - (size.width/2)
                origin.y = newCenter.y - (size.height/2)
            }
        }
    }
    //只读计算属性，只有getter没有setter的计算属性
    //只读计算属性的声明可以去掉get关键字和花括号
    struct Cuboid {
        var width = 0.0,height = 0.0, depth = 0.0
        var volume:Double{
         return width * height * depth
        }
        
    }
    //属性观察器：监控和响应属性值的变化，每次属性被设置值的时候都会调用属性观察器，甚至新的值和现在的值相同的时候也不例外。
    //可以为除了延迟储存属性之外的其他属性添加属性观察器
    class StepCounter {
        
        var totalSteps:Int = 0 {
            //在新的值被设置之前调用,新的值没有被命名默认为newValue
            willSet(newTotalSteps){
               
                print("About to set totalSteps to \(newTotalSteps - totalSteps)")
            }
            //在新的值被设置之后立即调用,旧值默认为oldValue
            didSet{
                
                if totalSteps>oldValue{
                    
                    print("Added \(totalSteps-oldValue) steps")
                    
                }
                
            }
        }
        
    }
    let stepCounter = StepCounter()
    //全局变量和局部变量
    //全局变量实在函数、方法、闭包或者任何类型之外定义的变量，局部变量是在函数方法或者闭包内部定义的变量。
    
    //类型属性：也可以为类型本身定义属性，不管类型有多少个实例，这些属性都只有唯一一份。可以用类直接访问的属性
}



